package com.gitee.chili.leisure.util;

import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.gitee.chili.leisure.constant.Constant;
import com.gitee.chili.leisure.util.functional.Function;
import org.springframework.util.StringUtils;

import java.util.Collection;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;
import java.util.function.Consumer;
import java.util.function.Predicate;

/**
 * CommonUtil
 *
 * @author week solider
 * @since 2020-07-03
 */
public class Utils {


    /**
     * 为指定的参数给定一个默认值，默认值的类型一点是给定参数的类型
     * 给定参数可以是任意类型
     *
     * @return 当给定参数不是字符串却为 {@code null} 时
     * 当给定参数时字符串却长度为 {@code 0} 时
     */
    public static <T> T defaultValue(T value, T defaultValue) {
        if (Objects.equals(value, defaultValue)) {
            return value;
        }
        if (value instanceof String)
            return StringUtils.hasLength(value.toString()) ? value : defaultValue;
        return Objects.isNull(value) ? defaultValue : value;
    }

    /**
     * 用 {@code pattern} 的方式将 {@code param} 连接在一起
     *
     * @param pattern 连接字符串的方式
     * @param params  需要连接的字符串
     */
    public static String concat(String pattern, String... params) {
        StringBuilder builder = new StringBuilder();

        // 连接方式不为空 避免没必要的开销
        final boolean isNotBlank = StrUtil.isNotBlank(pattern);

        // 连接参数
        Function.foreach(params.length, i -> {
            builder.append(params[i]);
            if (isNotBlank && i != params.length - 1) {
                builder.append(pattern);
            }
        });
        return builder.toString();
    }

    /**
     * {@link #concat(String, String...)}
     */
    public static String connect(String... params) {
        return concat(Constant.empty, params);
    }

    /**
     * 判断多个参数是否为{@code null} , 当参数为一个或没有时，判断也不会出错
     * 但这里更推荐使用 {@link StringUtils#isEmpty(Object)} 来校验单个参数
     *
     * @param params 参数集
     * @return 当有一个参数为 {@code null} 结果就是 {@code false}
     */
    public static boolean isEmpty(String... params) {
        if (Objects.isNull(params) || params.length < 1) {
            return true;
        }
        for (String param : params) {
            if (StringUtils.isEmpty(param))
                return true;
        }
        return false;
    }

    /**
     * {@link #isEmpty(String...)}
     */
    public static boolean nonEmpty(String... params) {
        return !isEmpty(params);
    }

    /**
     * 验证一个列表是否有元素 ，可以是任意一个列表类型
     *
     * @param value 需要校验的参数
     * @return has length
     */
    public static <T extends Collection<E>, E> boolean nonEmpty(T value) {
        return Objects.nonNull(value) && !value.isEmpty();
    }

    /**
     * {@link #nonEmpty(Collection)} 取反
     */
    public static <T extends Collection<E>, E> boolean isEmpty(T value) {
        return !nonEmpty(value);
    }

    /**
     * 验证一个集合是否有元素 ，可以是任意一个合集类型
     *
     * @param value 需要校验的参数
     * @return has length
     */
    public static <T extends Map<K, V>, K, V> boolean nonEmpty(T value) {
        return Objects.nonNull(value) && !value.isEmpty();
    }

    /**
     * {@link #nonEmpty(Map)} 取反
     */
    public static <T extends Map<K, V>, K, V> boolean isEmpty(T value) {
        return !nonEmpty(value);
    }

    /**
     * 随机生成6位数字
     */
    public static Long randomDigital() {
        return (long) ((Math.random() * 9 + 1) * 100000);
    }

    /**
     * Object 转 Long 类型，前提是必须是一个数字类型，否则会抛出异常
     *
     * @param obj 需要转换的参数
     */
    public static Long asLong(Object obj) {
        String value = String.valueOf(obj);
        if (NumberUtil.isNumber(value)) {
            return Long.parseLong(value);
        }
        throw new IllegalStateException("Conversion type exception , Parameter is not a numeric type. value = " + value);
    }

    /**
     * 从一个集合中获取指定的第一个元素，对元素进行处理逻辑，结合 {@code java 8 stream} 流对象实现
     *
     * @param collection 数据集合
     * @param predicate  过滤条件
     * @param consumer   条件通过执行的函数
     *
     * @see Predicate 条件是否通过
     * @see Optional  限制非空的约束作用
     * @see Consumer  执行一段给的参数的方法
     */
    public static <E> void accept(Collection<E> collection, Predicate<E> predicate, Consumer<? super E> consumer) {
        collection.stream().filter(predicate).findFirst().ifPresent(consumer);
    }

    public static void main(String[] args) {
        System.out.println(randomDigital());
    }

}
